package com.zto.sch.advance.caffeine;

import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @program: sch-diy-parent
 * @description:同步加载
 * @author: sch
 * @create: 2020-12-25 18:33
 **/
public class CaffeineDemoAsyncLoadingCache {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        AsyncLoadingCache<Object, String> cache = Caffeine.newBuilder()
                // 基于时间失效,写入之后开始计时失效
                .expireAfterWrite(2000, TimeUnit.MILLISECONDS)
                // 缓存容量
                .maximumSize(5)
                // 可以使用java8函数式接口的方式,这里其实是重写CacheLoader的load方法
                .buildAsync(key -> key + "_" + System.currentTimeMillis());

        // 获取一个不存在的kay,让它异步去调用CacheLoader的load方法。这时候他会返回一个CompletableFuture
        // 既:我已经帮你异步去运算key的值了,你什么时候要再什么时候调用CompletableFuture的get方法就好了
        CompletableFuture<String> future = cache.get("key");
        // 为了证明是异步调用,可以将时间戳打印出来和value中的时间戳比较.
        future.thenAccept(s -> System.out.println("当前的时间为:" + System.currentTimeMillis() + " -> 异步加载的值为:" + s));

        // 睡眠2秒让它的key失效
        TimeUnit.SECONDS.sleep(2);

        // 注意:当使用getIfPresent时,也是返回的CompletableFuture
        // 因为getIfPresent从缓存中找不到是不会去运算key既不会调用(CacheLoader.load)方法
        // 所以得到的CompletableFuture可能会为null,如果想从CompletableFuture中取值的话.先判断CompletableFuture是否会为null
        CompletableFuture<String> completableFuture = cache.getIfPresent("key");
        if (Objects.nonNull(completableFuture)) {
            System.out.println(completableFuture.get());
        }

    }
}
